import _3d from '../../_3d.js'
import { MTLLoader } from "../../threeLibs/loaders/MTLLoader.js"
import { OBJLoader2 } from "../../threeLibs/loaders/OBJLoader2.js"
import { MtlObjBridge } from "../../threeLibs/loaders/obj2/bridge/MtlObjBridge.js"
import { DRACOLoader } from '../../threeLibs/loaders/DRACOLoader.js'
import { GLTFLoader } from '../../threeLibs/loaders/GLTFLoader.js'
import { ColladaLoader } from '../../threeLibs/loaders/ColladaLoader.js'
import { FBXLoader } from '../../threeLibs/loaders/FBXLoader.js'
const forIt = function (parent, kind, app) {
    kind.forEach(e => {
        let object
        if(!e.object && !e.type ) {
            return console.error('对于一个对象，你必须要指定一个object属性，或者type属性，否则无法生成该对象')
        }
        else {
            if( e.object) { // others
                object = e.object
                initObject(app, object,parent, e)
            }
            else if( e.type ){
                if(e.type === 'group') {
                    object = new _3d.Group()
                    initObject(app, object,parent, e)
                }else if(e.type === 'model') {
                    app.load({
                        type: e.modelType,
                        url: e.url,
                        mtlUrl: e.mtlUrl,
                        dracoUrl: e.dracoUrl,
                        onLoad: obj => {
                            object = ['gltf','glb', 'dae'].includes(e.modelType) ? obj.scene : obj
                            initObject(app, object,parent, e, obj)
                        }
                    })

                }
            }
        }
    })
}
const initObject = function (app,object,parent, e, obj) {
    object.name = e.name || ''
    e.position ? object.position.set( e.position[0], e.position[1], e.position[2]) : ''
    e.scale? object.scale.set( e.scale[0], e.scale[1], e.scale[2]) : ''
    parent.add(object)
    e.callback &&  typeof e.callback === 'function' ? e.callback(object, obj) : ''

    // 等物体加载后才克隆
    initClone(app, object,parent, e)
    // 等物体加载后才遍历children 再开始进行
    if(e.children) forIt(object, e.children, app)

}
const initClone = function (app, object,parent, e) {
    if(e.clone && e.cloneAttribute) {
        e.cloneAttribute.forEach(m => {
            const obj = object.clone()
            obj.name = obj
            initObject(app, obj, parent, m)
            if(m.children) {
                forIt(obj, m.children, app)
            }
        })
    }
}


const obj = {
    // 加载模型图片
    load(option) { //模型加载器还不能单例设计模式，防止冲突
        if(option.type === 'image') {
            const loader = this.single.textureLoader ? this.single.textureLoader : this.single.textureLoader =  new _3d.TextureLoader()
            return loader.load(option.url, option.onLoad, option.onProgress , option.onError)
        }else if(option.type === 'json') {
            return new _3d.ObjectLoader().load(option.url, option.onLoad, option.onProgress , option.onError)
        }else if(option.type === 'obj') {
            const objLoader = new OBJLoader2()
            new MTLLoader().load(option.mtlUrl || '', function (mtlParseResult) {
                mtlParseResult.preload()
                // objLoader.setLogging( true, true ) //打印日志
                objLoader.addMaterials( MtlObjBridge.addMaterialsFromMtlLoader( mtlParseResult ), true )
                objLoader.load( option.url, option.onLoad, option.onProgress , option.onError )
            })
        }else if(option.type === 'gltf' || option.type === 'glb') {
            const gltfLoader =  new GLTFLoader()
            const dracoLoader =  new DRACOLoader()
            dracoLoader.setDecoderPath( option.dracoUrl )
            gltfLoader.setDRACOLoader( dracoLoader )
            gltfLoader.load(option.url, option.onLoad, option.onProgress , option.onError)
        }else if(option.type === 'dae') {
            new ColladaLoader().load(option.url, option.onLoad, option.onProgress , option.onError)
        }else if(option.type === 'fbx') {
            new FBXLoader().load(option.url, option.onLoad, option.onProgress , option.onError)
        }
        else console.error('(T ^ T) 当前只支持 image, json, obj, gltf, glb, dae, fbx 格式， 其他的模型请自行引入加载器')
    },
    // 迭代加载
    iterateLoad(objFileList, onProgress, onAllLoad) {
        let  fileIndex = 0
        let that = this
        function iterateLoadForIt() {
            that.load({
                type: objFileList[fileIndex].type,
                dracoUrl: objFileList[fileIndex].dracoUrl,
                mtlUrl: objFileList[fileIndex].mtlUrl,
                url: objFileList[fileIndex].url,
                onLoad: function (object) {
                    if(objFileList[fileIndex].onLoad) objFileList[fileIndex].onLoad(object)
                    //
                    fileIndex ++
                    if(fileIndex < objFileList.length) {
                        iterateLoadForIt()
                    }else {
                        if(onAllLoad) onAllLoad()
                    }
                },
                onProgress: function (xhr) {
                    if(objFileList[fileIndex].onProgress) objFileList[fileIndex].onProgress(xhr, fileIndex)
                    if(onProgress) onProgress(xhr, fileIndex)
                }
            })
        }
        iterateLoadForIt()
    }
}


export default obj